package cz.muni.fi.pa165.travelagency.cli;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

/**
 *
 * @author Jan Novotny
 */
public class CommandParser {

    static final String CONTEXT_PATH = System.getProperty("webapp.url", "http://localhost:8080/pa165");

    private CommandLineParser parser;
    private Options options;

    public CommandParser() {
        parser = new BasicParser();
        options = new Options();
        
        // services
        options.addOption("c", "customer", false, "Customer service");
        options.addOption("p", "packageTour", false, "PackageTour service");
        
        // operations
        options.addOption("get", "get", true, "Get an entity with specified Id");
        options.addOption("getByName", "getByName", true, "Get entities with specified name");
        options.addOption("all", "all", false, "Get all entities");
        options.addOption("create", "create", false, "Create entity");
        options.addOption("update", "update", false, "Update entity");
        options.addOption("delete", "delete", true, "Delete entity");
        
        // parameters
        options.addOption("id", "entityId", true, "Entity id");
        options.addOption("name", "entityName", true, "Entity name");
        options.addOption("address", "customerAddress", true, "Customer address");
        options.addOption("phone", "customerPhone", true, "Customer phone number");
        options.addOption("capacity", "ptCapacity", true, "PackageTour capacity");
        options.addOption("description", "ptDescription", true, "PackageTour description");
        options.addOption("destination", "ptDestination", true, "PackageTour destination");
        options.addOption("price", "ptPricePerPerson", true, "PackageTour price per person");
        options.addOption("start", "ptStartDate", true, "PackageTour date of start");
        options.addOption("end", "ptEndDate", true, "PackageTour date of end");

        //extra
        options.addOption("d", "debug", false, "Show debug info");
    }

    static void printUsageInfo() {
        System.out.println("Usage:");
        
        System.out.println("    Customer commands:");
        System.out.println("\t-c -get id");
        System.out.println("\t-c -getByName \"name\"");
        System.out.println("\t-c -all");
        System.out.println("\t-c -create -name \"name\" -address \"address\" -phone \"phone\"");
        System.out.println("\t-c -update -id id -cname \"name\" -address \"address\" -phone \"phone\"");
        System.out.println("\t-c -delete id");
        
        System.out.println("    PackageTour commands:");
        System.out.println("\t-p -get id");
        System.out.println("\t-p -all");
        System.out.println("\t-p -create -name \"name\" -capacity capacity -description \"description\"");
        System.out.println("\t   -destination \"destination\" -start \"dd.MM.yyyy\" -end \"dd.MM.yyyy\" -price pricePerPerson");
        System.out.println("\t-p -update -id id -name \"name\" -capacity capacity -description \"description\"");
        System.out.println("\t   -destination \"destination\" -start \"dd.MM.yyyy\" -end \"dd.MM.yyyy\" -price pricePerPerson");
        System.out.println("\t-p -delete id");  

        System.out.println("    Extra commands:");
        System.out.println("\t-d -show debug info (SOAP messages)");
    }

    void parse(String[] args) {
        
        CommandLine commandLine = null;
        try {
            commandLine = parser.parse(options, args);
        } catch (ParseException ex) {
            ShowError("Error: arguments couldn't be parsed.", true, true);
        }
        
        if (commandLine.hasOption("d")) {
            System.setProperty("com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true");
        }
        if (commandLine.hasOption("c")) {
            parseCustomerServiceRequest(commandLine);
        } else if (commandLine.hasOption("p")) {
            parsePackageTourServiceRequest(commandLine);
        } else {
            ShowError("Error: Service has to be specified.", true, true);
        }
    }

    private void parseCustomerServiceRequest(CommandLine commandLine) {
        System.out.println("Customer service request");
        
        if (commandLine.hasOption("get")) {
            CommandCustomerService.getCustomer(commandLine.getOptionValue("get"));
        } else if (commandLine.hasOption("delete")) {
            CommandCustomerService.deleteCustomer(commandLine.getOptionValue("delete"));
        } else if (commandLine.hasOption("getByName")) {
            CommandCustomerService.getCustomersByName(commandLine.getOptionValue("getByName"));
        } else if (commandLine.hasOption("all")) {
            CommandCustomerService.getAllCustomers();
        } else if (commandLine.hasOption("create")) {
            String name = commandLine.getOptionValue("name");
            String address = commandLine.getOptionValue("address");
            String phoneNumber = commandLine.getOptionValue("phone");
            
            if (name != null && address != null && phoneNumber != null) {
                CommandCustomerService.createCustomer(name, address, phoneNumber);
            } else {
                showError("Error: couldn't create new customer - some attributes are missing", true);
            } 
        } else if (commandLine.hasOption("update")) {
            Long id = null;
            try {
                id = Long.parseLong(commandLine.getOptionValue("id"));
            } catch (NumberFormatException e) {
                ShowError("Error: couldn't parse id", true, true);
            }
            String name = commandLine.getOptionValue("name");
            String address = commandLine.getOptionValue("address");
            String phoneNumber = commandLine.getOptionValue("phone");
            
            if (id != null && name != null && address != null && phoneNumber != null) {
                CommandCustomerService.updateCustomer(id, name, address, phoneNumber);
            } else {
                showError("Error: couldn't update customer - some attributes are missing", true);
            } 
        }        
    }

    private void parsePackageTourServiceRequest(CommandLine commandLine) {
        if (commandLine.hasOption("get")) {
            CommandPackageTourService.getPackageTour(commandLine.getOptionValue("get"));
        } else if (commandLine.hasOption("delete")) {
            CommandPackageTourService.deletePackageTour(commandLine.getOptionValue("delete"));
        } else if (commandLine.hasOption("all")) {
            CommandPackageTourService.getAllPackageTours();
        } else if (commandLine.hasOption("create")) {
            String name = commandLine.getOptionValue("name");
            int capacity = 0;
            try {
                capacity = Integer.parseInt(commandLine.getOptionValue("capacity"));
            } catch (NumberFormatException e) {
                ShowError("Error: couldn't parse capacity", true, true);
            }            
            String destination = commandLine.getOptionValue("destination");
            String description = commandLine.getOptionValue("description");
            BigDecimal price = null;
            try {
                price = BigDecimal.valueOf(Integer.parseInt(commandLine.getOptionValue("price")));
            } catch (NumberFormatException e) {
                ShowError("Error: couldn't parse price", true, true);
            }
            
            DateFormat f = new SimpleDateFormat("dd.MM.yyyy");
            Calendar start = Calendar.getInstance();
            try {
                start.setTime(f.parse(commandLine.getOptionValue("start")));
            } catch (java.text.ParseException ex) {
                ShowError("Error: couldn't parse start date", true, true);
            }
            GregorianCalendar end = (GregorianCalendar) Calendar.getInstance();
            try {
                end.setTime(f.parse(commandLine.getOptionValue("end")));
            } catch (java.text.ParseException ex) {
                ShowError("Error: couldn't parse end date", true, true);
            }            
            
            if (name != null && destination != null && description != null && price != null && start != null && end != null) {
                CommandPackageTourService.createPackageTour(name, capacity, destination, description, price, start, end);
            } else {
                showError("Error: couldn't create new package tour - some attributes are missing", true);
            } 
        } else if (commandLine.hasOption("update")) {
            Long id = null;
            try {
                id = Long.parseLong(commandLine.getOptionValue("id"));
            } catch (NumberFormatException e) {
                ShowError("Error: couldn't parse id", true, true);
            }
            String name = commandLine.getOptionValue("name");
            int capacity = 0;
            try {
                capacity = Integer.parseInt(commandLine.getOptionValue("capacity"));
            } catch (NumberFormatException e) {
                ShowError("Error: couldn't parse capacity", true, true);
            }            
            String destination = commandLine.getOptionValue("destination");
            String description = commandLine.getOptionValue("description");
            BigDecimal price = null;
            try {
                price = BigDecimal.valueOf(Integer.parseInt(commandLine.getOptionValue("price")));
            } catch (NumberFormatException e) {
                ShowError("Error: couldn't parse price", true, true);
            }                
            
            DateFormat f = new SimpleDateFormat("dd.MM.yyyy");
            Calendar start = Calendar.getInstance();
            try {
                start.setTime(f.parse(commandLine.getOptionValue("start")));
            } catch (java.text.ParseException ex) {
                ShowError("Error: couldn't parse start date", true, true);
            }
            Calendar end = Calendar.getInstance();
            try {
                end.setTime(f.parse(commandLine.getOptionValue("end")));
            } catch (java.text.ParseException ex) {
                ShowError("Error: couldn't parse end date", true, true);
            }     
            
            if (id != null && name != null && destination != null && description != null && price != null && start != null && end != null) {
                CommandPackageTourService.updatePackageTour(id, name, capacity, destination, description, price, start, end);
            } else {
                showError("Error: couldn't update package tour - some attributes are missing", true);
            } 
        }         
    }
    
    public static void showError(String text, boolean showUsage) {
        ShowError(text, showUsage, false);
    }
    
    public static void ShowError(String text, boolean showUsage, boolean exitApp) {
        System.err.println(text);
        
        if (showUsage) {
            printUsageInfo();
        }
        
        if (exitApp) {
            System.exit(1);
        }
    }
}
